home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_6 / SPINLOCK.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  10KB  |  354 lines

  1. /* spinlock.h: 32-bit Sparc spinlock support.
  2.  *
  3.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  4.  */
  5.  
  6. #ifndef __SPARC_SPINLOCK_H
  7. #define __SPARC_SPINLOCK_H
  8.  
  9. #ifndef __ASSEMBLY__
  10.  
  11. #ifndef __SMP__
  12.  
  13. typedef unsigned char spinlock_t;
  14. #define SPIN_LOCK_UNLOCKED 0
  15.  
  16. #define spin_lock_init(lock)    do { } while(0)
  17. #define spin_lock(lock)        do { } while(0)
  18. #define spin_trylock(lock)    do { } while(0)
  19. #define spin_unlock_wait(lock)    do { } while(0)
  20. #define spin_unlock(lock)    do { } while(0)
  21. #define spin_lock_irq(lock)    cli()
  22. #define spin_unlock_irq(lock)    sti()
  23.  
  24. #define spin_lock_irqsave(lock, flags)        save_and_cli(flags)
  25. #define spin_unlock_irqrestore(lock, flags)    restore_flags(flags)
  26.  
  27. /*
  28.  * Read-write spinlocks, allowing multiple readers
  29.  * but only one writer.
  30.  *
  31.  * NOTE! it is quite common to have readers in interrupts
  32.  * but no interrupt writers. For those circumstances we
  33.  * can "mix" irq-safe locks - any writer needs to get a
  34.  * irq-safe write-lock, but readers can get non-irqsafe
  35.  * read-locks.
  36.  */
  37. typedef struct { volatile unsigned int lock; } rwlock_t;
  38. #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  39.  
  40. #define read_lock(lock)        do { } while(0)
  41. #define read_unlock(lock)    do { } while(0)
  42. #define write_lock(lock)    do { } while(0)
  43. #define write_unlock(lock)    do { } while(0)
  44. #define read_lock_irq(lock)    cli()
  45. #define read_unlock_irq(lock)    sti()
  46. #define write_lock_irq(lock)    cli()
  47. #define write_unlock_irq(lock)    sti()
  48.  
  49. #define read_lock_irqsave(lock, flags)        save_and_cli(flags)
  50. #define read_unlock_irqrestore(lock, flags)    restore_flags(flags)
  51. #define write_lock_irqsave(lock, flags)        save_and_cli(flags)
  52. #define write_unlock_irqrestore(lock, flags)    restore_flags(flags)
  53.  
  54. #else /* !(__SMP__) */
  55.  
  56. #include <asm/psr.h>
  57.  
  58. /* Define this to use the verbose/debugging versions in arch/sparc/lib/debuglocks.c */
  59. #define SPIN_LOCK_DEBUG
  60.  
  61. #ifdef SPIN_LOCK_DEBUG
  62. struct _spinlock_debug {
  63.     unsigned char lock;
  64.     unsigned long owner_pc;
  65. };
  66. typedef struct _spinlock_debug spinlock_t;
  67.  
  68. #define SPIN_LOCK_UNLOCKED    (spinlock_t) { 0, 0 }
  69. #define spin_lock_init(lp)    do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0)
  70. #define spin_unlock_wait(lp)    do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
  71.  
  72. extern void _do_spin_lock(spinlock_t *lock, char *str);
  73. extern int _spin_trylock(spinlock_t *lock);
  74. extern void _do_spin_unlock(spinlock_t *lock);
  75.  
  76. #define spin_trylock(lp)    _spin_trylock(lp)
  77.  
  78. #define spin_lock(lock)        _do_spin_lock(lock, "spin_lock")
  79. #define spin_lock_irq(lock)    do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
  80. #define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
  81.  
  82. #define spin_unlock(lock)    _do_spin_unlock(lock)
  83. #define spin_unlock_irq(lock)    do { _do_spin_unlock(lock); __sti(); } while(0)
  84. #define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
  85.  
  86. struct _rwlock_debug {
  87.     volatile unsigned int lock;
  88.     unsigned long owner_pc;
  89.     unsigned long reader_pc[NCPUS];
  90. };
  91. typedef struct _rwlock_debug rwlock_t;
  92.  
  93. #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
  94.  
  95. extern void _do_read_lock(rwlock_t *rw, char *str);
  96. extern void _do_read_unlock(rwlock_t *rw, char *str);
  97. extern void _do_write_lock(rwlock_t *rw, char *str);
  98. extern void _do_write_unlock(rwlock_t *rw);
  99.  
  100. #define read_lock(lock)    \
  101. do {    unsigned long flags; \
  102.     __save_and_cli(flags); \
  103.     _do_read_lock(lock, "read_lock"); \
  104.     __restore_flags(flags); \
  105. } while(0)
  106. #define read_lock_irq(lock)    do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
  107. #define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
  108.  
  109. #define read_unlock(lock) \
  110. do {    unsigned long flags; \
  111.     __save_and_cli(flags); \
  112.     _do_read_unlock(lock, "read_unlock"); \
  113.     __restore_flags(flags); \
  114. } while(0)
  115. #define read_unlock_irq(lock)    do { _do_read_unlock(lock, "read_unlock_irq"); __sti(); } while(0)
  116. #define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
  117.  
  118. #define write_lock(lock) \
  119. do {    unsigned long flags; \
  120.     __save_and_cli(flags); \
  121.     _do_write_lock(lock, "write_lock"); \
  122.     __restore_flags(flags); \
  123. } while(0)
  124. #define write_lock_irq(lock)    do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
  125. #define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
  126.  
  127. #define write_unlock(lock) \
  128. do {    unsigned long flags; \
  129.     __save_and_cli(flags); \
  130.     _do_write_unlock(lock); \
  131.     __restore_flags(flags); \
  132. } while(0)
  133. #define write_unlock_irq(lock)    do { _do_write_unlock(lock); __sti(); } while(0)
  134. #define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
  135.  
  136. #else /* !SPIN_LOCK_DEBUG */
  137.  
  138. typedef unsigned char spinlock_t;
  139. #define SPIN_LOCK_UNLOCKED    0
  140.  
  141. #define spin_lock_init(lock)    (*(lock) = 0)
  142. #define spin_unlock_wait(lock)    do { barrier(); } while(*(volatile spinlock_t *)lock)
  143.  
  144. extern __inline__ void spin_lock(spinlock_t *lock)
  145. {
  146.     __asm__ __volatile__("
  147. 1:    ldstub    [%0], %%g2
  148.     orcc    %%g2, 0x0, %%g0
  149.     bne,a    2f
  150.      ldub    [%0], %%g2
  151.     .text    2
  152. 2:    orcc    %%g2, 0x0, %%g0
  153.     bne,a    2b
  154.      ldub    [%0], %%g2
  155.     b,a    1b
  156.     .previous
  157. "    : /* no outputs */
  158.     : "r" (lock)
  159.     : "g2", "memory", "cc");
  160. }
  161.  
  162. extern __inline__ int spin_trylock(spinlock_t *lock)
  163. {
  164.     unsigned int result;
  165.     __asm__ __volatile__("ldstub [%1], %0"
  166.                  : "=r" (result)
  167.                  : "r" (lock)
  168.                  : "memory");
  169.     return (result == 0);
  170. }
  171.  
  172. extern __inline__ void spin_unlock(spinlock_t *lock)
  173. {
  174.     __asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
  175. }
  176.  
  177. extern __inline__ void spin_lock_irq(spinlock_t *lock)
  178. {
  179.     __asm__ __volatile__("
  180.     rd    %%psr, %%g2
  181.     or    %%g2, %0, %%g2
  182.     wr    %%g2, 0x0, %%psr
  183.     nop; nop; nop;
  184. 1:    ldstub    [%1], %%g2
  185.     orcc    %%g2, 0x0, %%g0
  186.     bne,a    2f
  187.      ldub    [%1], %%g2
  188.     .text    2
  189. 2:    orcc    %%g2, 0x0, %%g0
  190.     bne,a    2b
  191.      ldub    [%1], %%g2
  192.     b,a    1b
  193.     .previous
  194. "    : /* No outputs */
  195.     : "i" (PSR_PIL), "r" (lock)
  196.     : "g2", "memory", "cc");
  197. }
  198.  
  199. extern __inline__ void spin_unlock_irq(spinlock_t *lock)
  200. {
  201.     __asm__ __volatile__("
  202.     rd    %%psr, %%g2
  203.     andn    %%g2, %1, %%g2
  204.     stb    %%g0, [%0]
  205.     wr    %%g2, 0x0, %%psr
  206.     nop; nop; nop;
  207. "    : /* No outputs. */
  208.     : "r" (lock), "i" (PSR_PIL)
  209.     : "g2", "memory");
  210. }
  211.  
  212. #define spin_lock_irqsave(__lock, flags)    \
  213. do {                        \
  214.     register spinlock_t *__lp asm("g1");    \
  215.     __lp = (__lock);            \
  216.     __asm__ __volatile__(            \
  217.     "rd    %%psr, %0\n\t"            \
  218.     "or    %0, %1, %%g2\n\t"        \
  219.     "wr    %%g2, 0x0, %%psr\n\t"        \
  220.     "nop; nop; nop;\n"            \
  221.     "1:\n\t"                \
  222.     "ldstub    [%2], %%g2\n\t"            \
  223.     "orcc    %%g2, 0x0, %%g0\n\t"        \
  224.     "bne,a    2f\n\t"                \
  225.     " ldub    [%2], %%g2\n\t"            \
  226.     ".text    2\n"                \
  227.     "2:\n\t"                \
  228.     "orcc    %%g2, 0x0, %%g0\n\t"        \
  229.     "bne,a    2b\n\t"                \
  230.     " ldub    [%2], %%g2\n\t"            \
  231.     "b,a    1b\n\t"                \
  232.     ".previous\n"                \
  233.     : "=r" (flags)                \
  234.     : "i" (PSR_PIL), "r" (__lp)        \
  235.     : "g2", "memory", "cc");        \
  236. } while(0)
  237.  
  238. extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
  239. {
  240.     __asm__ __volatile__("
  241.     stb    %%g0, [%0]
  242.     wr    %1, 0x0, %%psr
  243.     nop; nop; nop;
  244. "    : /* No outputs. */
  245.     : "r" (lock), "r" (flags)
  246.     : "memory", "cc");
  247. }
  248.  
  249. /* Read-write spinlocks, allowing multiple readers
  250.  * but only one writer.
  251.  *
  252.  * NOTE! it is quite common to have readers in interrupts
  253.  * but no interrupt writers. For those circumstances we
  254.  * can "mix" irq-safe locks - any writer needs to get a
  255.  * irq-safe write-lock, but readers can get non-irqsafe
  256.  * read-locks.
  257.  *
  258.  * XXX This might create some problems with my dual spinlock
  259.  * XXX scheme, deadlocks etc. -DaveM
  260.  */
  261. typedef struct { volatile unsigned int lock; } rwlock_t;
  262.  
  263. #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  264.  
  265. /* Sort of like atomic_t's on Sparc, but even more clever.
  266.  *
  267.  *    ------------------------------------
  268.  *    | 24-bit counter           | wlock |  rwlock_t
  269.  *    ------------------------------------
  270.  *     31                       8 7     0
  271.  *
  272.  * wlock signifies the one writer is in or somebody is updating
  273.  * counter. For a writer, if he successfully acquires the wlock,
  274.  * but counter is non-zero, he has to release the lock and wait,
  275.  * till both counter and wlock are zero.
  276.  *
  277.  * Unfortunately this scheme limits us to ~16,000,000 cpus.
  278.  */
  279. extern __inline__ void _read_lock(rwlock_t *rw)
  280. {
  281.     register rwlock_t *lp asm("g1");
  282.     lp = rw;
  283.     __asm__ __volatile__("
  284.     mov    %%o7, %%g4
  285.     call    ___rw_read_enter
  286.      ldstub    [%%g1 + 3], %%g2
  287. "    : /* no outputs */
  288.     : "r" (lp)
  289.     : "g2", "g4", "g7", "memory", "cc");
  290. }
  291.  
  292. #define read_lock(lock) \
  293. do {    unsigned long flags; \
  294.     __save_and_cli(flags); \
  295.     _read_lock(lock); \
  296.     __restore_flags(flags); \
  297. } while(0)
  298.  
  299. extern __inline__ void _read_unlock(rwlock_t *rw)
  300. {
  301.     register rwlock_t *lp asm("g1");
  302.     lp = rw;
  303.     __asm__ __volatile__("
  304.     mov    %%o7, %%g4
  305.     call    ___rw_read_exit
  306.      ldstub    [%%g1 + 3], %%g2
  307. "    : /* no outputs */
  308.     : "r" (lp)
  309.     : "g2", "g4", "g7", "memory", "cc");
  310. }
  311.  
  312. #define read_unlock(lock) \
  313. do {    unsigned long flags; \
  314.     __save_and_cli(flags); \
  315.     _read_unlock(lock); \
  316.     __restore_flags(flags); \
  317. } while(0)
  318.  
  319. extern __inline__ void write_lock(rwlock_t *rw)
  320. {
  321.     register rwlock_t *lp asm("g1");
  322.     lp = rw;
  323.     __asm__ __volatile__("
  324.     mov    %%o7, %%g4
  325.     call    ___rw_write_enter
  326.      ldstub    [%%g1 + 3], %%g2
  327. "    : /* no outputs */
  328.     : "r" (lp)
  329.     : "g2", "g4", "g7", "memory", "cc");
  330. }
  331.  
  332. #define write_unlock(rw)    do { (rw)->lock = 0; } while(0)
  333. #define read_lock_irq(lock)    do { __cli(); _read_lock(lock); } while (0)
  334. #define read_unlock_irq(lock)    do { _read_unlock(lock); __sti(); } while (0)
  335. #define write_lock_irq(lock)    do { __cli(); write_lock(lock); } while (0)
  336. #define write_unlock_irq(lock)    do { write_unlock(lock); __sti(); } while (0)
  337.  
  338. #define read_lock_irqsave(lock, flags)    \
  339.     do { __save_and_cli(flags); _read_lock(lock); } while (0)
  340. #define read_unlock_irqrestore(lock, flags) \
  341.     do { _read_unlock(lock); __restore_flags(flags); } while (0)
  342. #define write_lock_irqsave(lock, flags)    \
  343.     do { __save_and_cli(flags); write_lock(lock); } while (0)
  344. #define write_unlock_irqrestore(lock, flags) \
  345.     do { write_unlock(lock); __restore_flags(flags); } while (0)
  346.  
  347. #endif /* SPIN_LOCK_DEBUG */
  348.  
  349. #endif /* __SMP__ */
  350.  
  351. #endif /* !(__ASSEMBLY__) */
  352.  
  353. #endif /* __SPARC_SPINLOCK_H */
  354.